﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using OneDollarStore.Models;

namespace OneDollarStore.Controllers
{
    public class ProductController : Controller
    {
        StoreModelEntities storeDB = new StoreModelEntities();

        // page: current page number
        // pageSize: number of products per page
        // sorting: by Category, Manufacturer or Price
        // order: descending or ascending
        // Render products
        public ViewResult Index(int? page, int? pageSize, string sorting, string order)
        {
            try
            {
                int pageNo = page ?? 1;
                int PageSize = pageSize ?? 8;
                // Highlight: show/hide a product
                var products = (from product in storeDB.SerialProducts.Include("Category")
                                    .Include("Laptop").Include("Desktop").Include("Mainboard")
                                    .Include("CPU").Include("RAM").Include("HDD").Include("VGA")
                                where product.Highlight == true
                                orderby product.Name
                                select product);
                if (sorting != null)
                {
                    if (sorting == "Category")
                    {
                        products.OrderBy(p => p.Category.Name);
                    }
                    else if (sorting == "Manufacturer")
                    {
                        products.OrderBy(p => p.Manufacturer.Name);
                    }
                    else if (sorting == "Price")
                    {
                        products.OrderBy(p => p.RetailPrice);
                    }
                    if (order == "desc")
                    {
                        products.Reverse();
                    }
                }
                var productModel = new ProductModel();
                // Select which products to be shown depends on pageNo
                productModel.Products = products.Skip((pageNo - 1) * PageSize).Take(PageSize).ToList();
                int NumberOfItems = products.Count();
                productModel.NumberOfPages = (int)Math.Ceiling((decimal)NumberOfItems / PageSize);
                productModel.CurrentPage = pageNo;
                productModel.Message = String.Empty;
                // ~: Home page
                ViewData["Link"] = "~/Product/Index";
                return View(productModel);
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
                return View();
            }
        }

        // Render categories
        public PartialViewResult CategoryMenu()
        {
            var categories = (from category in storeDB.Categories
                              select category);
            return PartialView(categories);
        }

        // Render manufacturers
        public PartialViewResult ManufacturerMenu()
        {
            var manufacturers = (from manufacturer in storeDB.Manufacturers
                                 orderby manufacturer.Name
                                 select manufacturer);
            return PartialView(manufacturers);
        }

        // Render product details
        public PartialViewResult Details(int? id)
        {
            // Lambda expression
            var productDetails = storeDB.SerialProducts.Include("Category")
                                    .Include("Laptop").Include("Desktop").Include("Mainboard")
                                    .Include("CPU").Include("RAM").Include("HDD").Include("VGA")
                                    .FirstOrDefault(p => p.SerialProductID == id);
            return PartialView(productDetails);
        }

        // Take all products which belong to id category
        // id: Category name
        public ViewResult Category(string id, int? page, int? pageSize, string sorting, string order)
        {
            try
            {
                int pageNo = page ?? 1;
                int PageSize = pageSize ?? 8;
                var products = (from product in storeDB.SerialProducts.Include("Category")
                                    .Include("Laptop").Include("Desktop").Include("Mainboard")
                                    .Include("CPU").Include("RAM").Include("HDD").Include("VGA")
                                where product.Category.Name == id
                                orderby product.Name
                                select product);
                if (sorting != null)
                {
                    if (sorting == "Category")
                    {
                        products.OrderBy(p => p.Category.Name);
                    }
                    else if (sorting == "Manufacturer")
                    {
                        products.OrderBy(p => p.Manufacturer.Name);
                    }
                    else if (sorting == "Price")
                    {
                        products.OrderBy(p => p.RetailPrice);
                    }
                    if (order == "desc")
                    {
                        products.Reverse();
                    }
                }
                var productModel = new ProductModel();
                productModel.Products = products.Skip((pageNo - 1) * PageSize).Take(PageSize).ToList();
                int NumberOfItems = products.Count();
                productModel.NumberOfPages = (int)Math.Ceiling((decimal)NumberOfItems / PageSize);
                productModel.CurrentPage = pageNo;
                productModel.Message = id;
                ViewData["Link"] = "~/Product/Category/" + id;
                return View("Index", productModel);
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
                return View();
            }
        }

        // Take all products which belong to id manufacturer
        // id: Manufacturer name
        public ViewResult Manufacturer(string id, int? page, int? pageSize, string sorting, string order)
        {
            try
            {
                int pageNo = page ?? 1;
                int PageSize = pageSize ?? 8;
                var products = (from product in storeDB.SerialProducts.Include("Category")
                                    .Include("Laptop").Include("Desktop").Include("Mainboard")
                                    .Include("CPU").Include("RAM").Include("HDD").Include("VGA")
                                where product.Manufacturer.Name == id
                                orderby product.Name
                                select product);
                if (sorting != null)
                {
                    if (sorting == "Category")
                    {
                        products.OrderBy(p => p.Category.Name);
                    }
                    else if (sorting == "Manufacturer")
                    {
                        products.OrderBy(p => p.Manufacturer.Name);
                    }
                    else if (sorting == "Price")
                    {
                        products.OrderBy(p => p.RetailPrice);
                    }
                    if (order == "desc")
                    {
                        products.Reverse();
                    }
                }
                var productModel = new ProductModel();
                productModel.Products = products.Skip((pageNo - 1) * PageSize).Take(PageSize).ToList();
                int NumberOfItems = products.Count();
                productModel.NumberOfPages = (int)Math.Ceiling((decimal)NumberOfItems / PageSize);
                productModel.CurrentPage = pageNo;
                productModel.Message = id;
                ViewData["Link"] = "~/Product/Manufacturer/" + id;
                return View("Index", productModel);
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
                return View();
            }
        }

        // Search function
        public ViewResult Search(string keywords, int? page, int? pageSize, string sorting, string order)
        {
            try
            {
                int pageNo = page ?? 1;
                int PageSize = pageSize ?? 8;
                var products = (from product in storeDB.SerialProducts.Include("Category")
                                    .Include("Laptop").Include("Desktop").Include("Mainboard")
                                    .Include("CPU").Include("RAM").Include("HDD").Include("VGA")
                                where product.Name.Contains(keywords)
                                orderby product.Name
                                select product);
                var productModel = new ProductModel();
                productModel.Products = products.Skip((pageNo - 1) * PageSize).Take(PageSize).ToList();
                int NumberOfItems = products.Count();
                productModel.NumberOfPages = (int)Math.Ceiling((decimal)NumberOfItems / PageSize);
                productModel.CurrentPage = pageNo;
                productModel.Message = keywords;
                ViewData["Link"] = "~/Product/Search" + keywords;
                // How many items that match the criteria
                ViewData["NumberOfItems"] = NumberOfItems;
                return View(productModel);
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
                return View();
            }
        }

        // Take all products in promotion state
        public ViewResult Promotion(int? page, int? pageSize, string sorting, string order)
        {
            try
            {
                int pageNo = page ?? 1;
                int PageSize = pageSize ?? 8;
                // Highlight: show/hide a product
                var products = (from product in storeDB.SerialProducts.Include("Category")
                                    .Include("Laptop").Include("Desktop").Include("Mainboard")
                                    .Include("CPU").Include("RAM").Include("HDD").Include("VGA")
                                where ((product.Highlight == true) && (product.PromotionPrice != null) && (product.PromotionEndDate >= DateTime.Today))
                                orderby product.Name
                                select product);
                if (sorting != null)
                {
                    if (sorting == "Category")
                    {
                        products.OrderBy(p => p.Category.Name);
                    }
                    else if (sorting == "Manufacturer")
                    {
                        products.OrderBy(p => p.Manufacturer.Name);
                    }
                    else if (sorting == "Price")
                    {
                        products.OrderBy(p => p.RetailPrice);
                    }
                    if (order == "desc")
                    {
                        products.Reverse();
                    }
                }
                var productModel = new ProductModel();
                // Select which products to be shown depends on pageNo
                productModel.Products = products.Skip((pageNo - 1) * PageSize).Take(PageSize).ToList();
                int NumberOfItems = products.Count();
                productModel.NumberOfPages = (int)Math.Ceiling((decimal)NumberOfItems / PageSize);
                productModel.CurrentPage = pageNo;
                productModel.Message = "Promotion";
                // ~: Home page
                ViewData["Link"] = "~/Product/" + productModel.Message;
                return View("Index", productModel);
            }
            catch (Exception ex)
            {
                Response.Write(ex.Message);
                return View();
            }
        }
    }
}